iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
Modern Web

30天React練功坊-攻克常見實務/面試問題系列 第 26

30天React練功坊-攻克常見實務/面試問題 Day26: Add emojis to the page onclick(interview question)

  • 分享至 

  • xImage
  •  
tags: ItIron2023 react

前言

我們昨天做了一個簡單的pagination題目,大致上了解一般實務是如何處理這類的情況,包含loading & hasMore的小細節,只要你能掌握基本的useState & useEffect應該就難不倒你!今天我們來看一個變化題吧,這並不是實務上真正會出現的情境,但卻是我之前在面試一間多媒體美商時遇到的面試問題,後來也發現其他公司也有出過類似的題目,就把這個題目收藏起來了,馬上來瞧一瞧吧!

本日題目

請觀察這個codesandbox以及下方的starter code。

import "./styles.css";

function App() {  
  const fruitEmojis = ["🍎", "🍊", "🍇", "🍓", "🍒"];

  return (
    <div
      style={{ width: "100vw", height: "100vh", position: "relative" }}
    >
      <h1>Click to add an fruit emoji 🍎🍊🍇</h1>
      // Display your emojis
    </div>
  );
}

export default App;
.emoji {
  height: 24px;
  width: 24px;
  display: grid;
  place-items: center;
  user-select: none;
}

今天你要做的事情相當單純,你需要在使用者點擊畫面中的任何地方時建立一個Emoji,如下圖所示

day26-demo-gif

請注意以下的事項並完成題目的要求

1. 每次點擊時應從fruitEmojis陣列中隨機選一個emoji產生
2. 請勿移除styles.css中.emoji的任何樣式(你可以新增),並請勿移除起始js檔案內的樣式
3. 產生的emoji元素需用指定的格式<span img='role' className="emoji">Emoji放這</span>
4. 你可以使用event.clientX & event.clientY來取得使用者點擊的位置

解答與基本解釋

這是個有趣的題目,基本上我是忠實呈現當時被問的情境,唯獨我給予你們更多的提示以便我加快速度,首先要做到這樣的效果我們勢必需要一個state管理所有產生的emoji(其實這句話不一定正確,你大可以直接在畫面加上emoji而不用任何的state管理,但這樣後續要操作這些產生的emoji難度就提高了不少)。

你大概可以猜到我們最終需要一個陣列並配合map方法渲染出所有的emojis,最好還另外做一個獨立的Emoji組件,那麼我們就必須釐清這個emoji有哪些元素是必備的

1. 使用者點擊的x座標
2. 使用者點擊的y座標
3. 一個獨特的id
4. 是哪個水果emoji

有了這些之後你的Emoji組件就呼之欲出了,有了x & y座標,接著我們只要配合position: 'absolute'就可以輕易讓emoji出現在我們的點擊的位置,你可以先完成以下的部分,以下是其中一種寫法。

import React, { useState } from "react";

const Emoji = ({ x, y, emoji }) => (
  <span
    className="emoji"
    role="img"  
    style={{
      position: "absolute",
      left: `${x}px`,
      top: `${y}px`
    }}
  >
    {emoji}
  </span>
);

function App() {
  const [emojis, setEmojis] = useState([]);
  const fruitEmojis = ["🍎", "🍊", "🍇", "🍓", "🍒"];

  return (
    <div
      style={{ width: "100vw", height: "100vh", position: "relative" }}
    >
      <h1>Click to add an fruit emoji 🍎🍊🍇</h1>
      {emojis.map((emojiObj) => (
        <Emoji
          key={emojiObj.id}
          x={emojiObj.x}
          y={emojiObj.y}
          emoji={emojiObj.emoji}
        />
      ))}
    </div>
  );
}

export default App;

到這邊遊戲基本上就結束了,你只要再加上一個點擊的handler就可以順利完成題目,由於你需要在畫面上任何一個地方點擊都能產生emoji,你的onClick自然就需要掛載到最外層的div元素上,以下是一個基本的handleClick函數範例,獨特id的部分就容我偷懶一下用timestamp完成


function App() {
  const [emojis, setEmojis] = useState([]);
  const fruitEmojis = ["🍎", "🍊", "🍇", "🍓", "🍒"];

  const handleClick = (e) => { 
    const x = e.clientX;
    const y = e.clientY;
    const randomEmoji =
      fruitEmojis[Math.floor(Math.random() * fruitEmojis.length)];
    // 每次點擊時更新emoji陣列
    setEmojis((prevEmojis) => [
      ...prevEmojis,
      { id: Date.now(), x, y, emoji: randomEmoji }
    ]);
  };

  return (
    <div
      style={{ width: "100vw", height: "100vh", position: "relative" }}
      onClick={handleClick} // 加入click handler
    >
      <h1>Click to add an fruit emoji 🍎🍊🍇</h1>
      {emojis.map((emojiObj) => (
        <Emoji
          key={emojiObj.id}
          x={emojiObj.x}
          y={emojiObj.y}
          emoji={emojiObj.emoji}
        />
      ))}
    </div>
  );
}

export default App;

實際去操作後你會發現確實有在點擊的地方順利產生emoji,不過位置稍稍有些偏差,類似下圖的效果。

day26-demo-gif-2

這主要是因為我們是根據使用者點擊的位置來抓x & y座標,抓到點後會從左上角放置該emoji,這麼一來最終呈現的位置就會受到emoji本身的長寬影響導致看起來有些落差,因此你需要對展示的位置做一些微調,例如下方就會是根據元素本身的長寬做一些調整,這部分就完全根據UI的需求,若你需要讓產生的emoji完全在正中央,那麼你就得多下一點點工夫

const Emoji = ({ x, y, emoji }) => (
  <span
    className="emoji"
    role="img"  
    style={{
      position: "absolute",
      left: `${x - 24}px`, // 根據元素的寬度微調
      top: `${y - 24}px`   // 根據元素的長度微調
    }}
  >
    {emoji}
  </span>
);

總結

今天我們看了另一個有趣的題目,至少在畫面上看起來是更多采多姿一些,題目主要考驗點擊事件的處理以及稍稍有些複雜的state,在渲染陣列時也有map & key這些小地方需要注意,算是個不錯的起始問題,明天我們會根據這個問題繼續做一些延伸,完整地去模擬我當時面試的狀況,敬請期待!

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
30天React練功坊-攻克常見實務/面試問題 Day25: Implement simple pagination(interview question)
下一篇
30天React練功坊-攻克常見實務/面試問題 Day27: Add emojis to the page onclick PartII(interview question)
系列文
30天React練功坊-攻克常見實務/面試問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言